// Copyright (C) 2010  Andrew H. Chan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "packed_config.h"

int Packed_Config::loci_defined[NUM_HAPS];
int Packed_Config::breakpoints[NUM_HAPS];

size_t hash_value(Packed_Config const& packed_config) {
    return boost::hash<Packed_Config::data_type>()(packed_config.data);
}

int Packed_Config::next_hap(index_t& index, int max_allele) {
    int ii;
    int n = index.size();
    for(ii=0; (ii<n) && index[ii] == max_allele; ++ii) {
        index[ii] = -1;
    }
    if(ii<n) {
        ++index[ii];
        return 1;
    }
    return 0;
}

int Packed_Config::compute_loci() {
    index_t index = index_t(NUM_LOCI, -1);
    hap_id_t hap_id = 0;
    while(next_hap(index, NUM_ALLELES-1)) {
        int num_defined_loci = 0;
        // compute number of defined loci for hap
        for(index_t::const_iterator iter=index.begin(); iter!=index.end(); ++iter) {
            if(*iter != -1)
                ++num_defined_loci;
        }
        assert(hap_id < NUM_HAPS);
        loci_defined[hap_id] = num_defined_loci;
        ++hap_id;
    }
    return 0;
}

int Packed_Config::compute_breaks() {
    index_t index = index_t(NUM_LOCI, -1);
    hap_id_t hap_id = 0;
    while(next_hap(index, NUM_ALLELES-1)) {
        size_t left_pointer = 0;
        size_t right_pointer = 0;
        // get left pointer
        for(int ii=0; ii<static_cast<int>(NUM_LOCI); ++ii) {
            if(index[ii] != -1) {
                left_pointer = ii;
                break;
            }
        }
        // get right pointer
        for(int ii=NUM_LOCI-1; ii >= 0; --ii) {
            if(index[ii] != -1) {
                right_pointer = ii;
                break;
            }
        }
        int num_breaks = right_pointer - left_pointer;

        assert(num_breaks >= 0);
        assert(hap_id < NUM_HAPS);
        breakpoints[hap_id] = num_breaks;
        ++hap_id;
    }
    return 0;
}
